package cn.duhengkui.national.valuelist.gen.postgresql;

import java.io.IOException;
import java.io.Serializable;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;
import org.postgresql.util.PGobject;
import org.springframework.beans.BeanUtils;

import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;


/**
 * json对象映射
 * @author duhengkui
 *
 */
@SuppressWarnings("unused")
public class JSONobject<Attribute extends Serializable> extends PGobject {
	/**
	 * Logger for this class
	 */
	private static final Logger logger = Logger
			.getLogger(JSONobject.class);

	private static final long serialVersionUID = 3784022182076499241L;
	
	private static final String JSONB = "jsonb";
	
	private static final String JSON = "json";
	
	private Attribute attribute;
	
	
	/**
	 * 初始化 <code>EntityStructurationAttribute.java</code> 新实例。
	 */
	public JSONobject() {
		setType(JSONB);
	}
	
	
	/**
	 * 这里是JDBC读取数据封装Entity时使用的
	 * @param pGobject
	 * @param type
	 * @return
	 */
	public static <Attribute extends Serializable> JSONobject<Attribute> newInstance(final Object pGobject, Class<Attribute> type) {
		if(pGobject instanceof PGobject) {
			JSONobject<Attribute> that = new JSONobject<>();
			try {
				that.setAttribute(type.newInstance());
				that.setValue(((PGobject)pGobject).getValue());
			} catch (InstantiationException | IllegalAccessException | SQLException e) {
				logger.error(e);
				throw new RuntimeException(e);
			}
			return that;
		} else if(pGobject == null) {
			JSONobject<Attribute> that = new JSONobject<>();
			try {
				Attribute attribute = type.newInstance();
				that.setAttribute(attribute);
			} catch (InstantiationException | IllegalAccessException e) {
				logger.error(e);
				throw new RuntimeException(e);
			}
			return that;
		} else {
			throw new RuntimeException("Object is not " + PGobject.class.getName() + " type.");
		}
	}
	
	/* (non-Javadoc)
	 * @see org.postgresql.util.PGobject#setValue(java.lang.String)
	 */
	@Override
	public void setValue(String value) throws SQLException {
		super.setValue(value);
		try {
			ObjectMapper objectMapper = new ObjectMapper();
			objectMapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY);
			objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
			BeanUtils.copyProperties(objectMapper.readValue(value, attribute.getClass()), attribute);
		} catch (IOException e) {
			throw new JsonObjectRuntimeExceptioin("The json data :[ " + value + " ] cannot convert to '" + attribute.getClass().getName() + "' class!!", e);
		}
	}
	
	/**
	 * 执行查询语句后，读取原始json数据格式的value
	 * @return
	 */
	public String getJsonValue() {
		return super.getValue();
	}
	
	/* (non-Javadoc)
	 * @see org.postgresql.util.PGobject#getValue()
	 */
	@Override
	public String getValue() {
		try {
			ObjectMapper objectMapper = new ObjectMapper();
			objectMapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY);
			objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
			return objectMapper.writeValueAsString(attribute);
		} catch (JsonProcessingException e) {
			throw new JsonObjectRuntimeExceptioin(attribute.getClass().getName() + " : cannot be mapped 'jsonb' type!!", e);
		}
	}
	
	/* (non-Javadoc)
	 * @see org.postgresql.util.PGobject#toString()
	 */
	@Override
	public String toString() {
		return getValue();
	}

	/**
	 * @return the attribute
	 */
	public Attribute getAttribute() {
		return attribute;
	}

	/**
	 * @param attribute the attribute to set
	 */
	public JSONobject<Attribute> setAttribute(Attribute attribute) {
		this.attribute = attribute;
		return this;
	}
	
}
